#pragma once

#include <iostream>
#include <string>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <cstring>
#include <stdlib.h>
#include <errno.h>
#include <vector>
#include "Util.hpp"
#include "Reactor.hpp"

#define ONCE_SIZE 1024
static int RecverCore(int sock,std::string& inbuffer)
{
    while(true)
    {
        char buffer[ONCE_SIZE];
        ssize_t s = recv(sock,buffer,ONCE_SIZE-1,0);
        if(s > 0)
        {
            buffer[s] = 0;
            inbuffer += buffer;
        }
        else if(s == 0)
        {
            std::cout << "链接已关闭" << std::endl;

            return 0;
        }
        else
        {
            if(errno == EINTR) // 被信号打断
            {
                continue;
            }
            // 1.读取完成
            if(errno == EAGAIN || errno == EWOULDBLOCK)
            {
                return 1;// success
            }
            // 2.读取出错
            return -1;
        }
    }

}

int Recver(Event *evp)
{
    std::cout << "Recver is been called" << std::endl;
    // 真正的读取
    int result = RecverCore(evp->_sock,evp->inbuffer);
    if(result <= 0)
    {
        // 差错处理
        if(evp->_errorer) evp->_errorer(evp);
        return -1;
    }
    // 分包
    std::vector<std::string> tokens;
    std::string sep = "X";
    SplitSegment(evp->inbuffer,tokens,sep);
    // 对每个包进行处理
    for(auto& seg : tokens)
    {
        // 反序列化
        std::string out1,out2;
        Deserialize(seg,&out1,&out2);
        // 进行业务处理，构建响应
        int num1 = atoi(out1.c_str());
        int num2 = atoi(out2.c_str());
        int result = num1+num2;
        std::string send = out1.c_str();
        send += "+";
        send += out2.c_str();
        send += "=";
        send += std::to_string(result);
        send += sep; // 加入分隔符
        // 响应放入outbuffer
        evp->outbuffer += send;
    }
    // 报文处理完毕,通知可以发送
    if(!evp->outbuffer.empty())
    {
        // 将文件描述符设置为可读可写
        evp->R->EnableRW(evp->_sock,true,true);
    }
    return 0;// success
}

static int SenderCore(int sock,std::string& outbuffer)
{
    int total = 0;
    while(true)
    {
        const char* start = outbuffer.c_str();
        int size = outbuffer.size();
        ssize_t rs = send(sock,start+total,size-total,0);
        if(rs > 0)
        {
            total += rs;
            if(total == size)// 全部发送完毕
            {
                outbuffer.clear();
                return 1;// success
            }
        }
        else
        {
            if(errno == EINTR) // 被信号打断
            {
                continue; // 下轮继续发送
            }
            // 数据没有发完，但是不允许发了
            if(errno == EAGAIN || errno == EWOULDBLOCK)
            {
                // 把已经发送完的数据清理掉
                outbuffer.erase(0,total);
                return 0;
            }
            return -1;// 发送失败
        }
    }
}

int Sender(Event *evp)
{
    std::cout << "Sender is been called" << std::endl;
    int result = SenderCore(evp->_sock,evp->outbuffer);
    if(result == 1)
    {
        evp->R->EnableRW(evp->_sock,true,false); // 不需要写了，关闭写
    }
    else if(result == 0)
    {
        evp->R->EnableRW(evp->_sock,true,true); // 下次继续发
    }
    else
    {
        if(evp->_errorer)
            evp->_errorer(evp);
    }
    return 0;
}

int Errorer(Event *evp)
{
    std::cerr << "Erroer is cleaning.." << std::endl;
    evp->R->EraseEvent(evp);// 出错清理该事件
    return 0;
}